package com.itqf.controller;

import com.itqf.bean.DtsAdmin;
import com.itqf.captcha.CaptchaCodeManager;
import com.itqf.dto.LoginDto;
import com.itqf.service.DtsAdminService;
import com.itqf.util.Base64;
import com.itqf.util.ResponseUtil;
import com.itqf.utils.AdminResponseCode;
import com.itqf.utils.AdminResponseUtil;
import com.itqf.utils.AuthSupport;
import com.itqf.utils.VerifyCodeUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * projectName: gp_manage
 *
 * @author: 赵伟风
 * time: 2021/8/17 9:41
 * description:
 */
@RestController
@RequestMapping("admin/auth")
@CrossOrigin(allowCredentials = "true",value = "*")
public class AdminAuthController {

    @Autowired
    private DtsAdminService dtsAdminService;

    @Autowired
    private ApplicationContext applicationContext;

    private final static Logger LOGGER = LoggerFactory.getLogger(AdminAuthController.class);


    /**
     * 未认证
     * @return 状态码501
     */
    @GetMapping("/501")
    public Object unLogin(){

        return ResponseUtil.unlogin();
    }

    /**
     * 未授权
     * @return 状态码506
     */
    @GetMapping("/506")
    public Object unAuthc(){

        return ResponseUtil.unauthz();
    }

    /**
     * 验证成功
     * @return 状态码200
     */
    @GetMapping("/index")
    public Object index(){

        return ResponseUtil.ok();
    }

    /**
     * 验证码生成
     *    思考点：
     *       1.权限问题        匿名资源
     *       2.涉及的工具类问题
     *       3.参数和响应问题
     * @return
     */
    @GetMapping("captchaImage")
    public Object captchaImage() throws IOException {

        //1.生成验证码需要的参数  code  uuid
        String flagUid = UUID.randomUUID().toString().replaceAll("-", "");
        String code = VerifyCodeUtils.generateVerifyCode(4);

        //2.存储验证码
        boolean cache = CaptchaCodeManager.addToCache(flagUid, code, 3);

        //3.生成验证码图片
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        VerifyCodeUtils.outputImage(110, 36, baos, code);

        //4.转成base64
        String captchaImageStr = Base64.encode(baos.toByteArray());

        //5.封装结果返回
        Map<String,String> data = new HashMap<>();
        data.put("img", captchaImageStr);
        data.put("uuid", flagUid);

        return ResponseUtil.ok(data);
    }



    @PostMapping(value = "login",consumes = "application/json;charset=utf-8")
    public Object login(@RequestBody LoginDto loginDto, HttpServletRequest request){

        //1.校验传入的参数是否正确
        if (StringUtils.isEmpty(loginDto.getUsername()) || StringUtils.isEmpty(loginDto.getPassword())
            || StringUtils.isEmpty(loginDto.getCode()) || StringUtils.isEmpty(loginDto.getUuid())
        ){

            return ResponseUtil.badArgumentValue();
        }

        //2.校验验证码是否正确  过期 / 错误

        String cachedCaptcha = CaptchaCodeManager.getCachedCaptcha(loginDto.getUuid());

        if (cachedCaptcha == null) {
            //验证码过期
            return AdminResponseUtil.fail(AdminResponseCode.AUTH_CAPTCHA_EXPIRED);
        }

        if (!cachedCaptcha.equalsIgnoreCase(loginDto.getCode())){
            //验证码错误
            return AdminResponseUtil.fail(AdminResponseCode.AUTH_CAPTCHA_ERROR);
        }

        //3.认证操作
           //1.subject
           //2.usernameAndPasswordToken
           //3.认证
           //4.try / catch 捕捉认证错误

        Subject subject = SecurityUtils.getSubject();

        UsernamePasswordToken token = new UsernamePasswordToken(loginDto.getUsername(),loginDto.getPassword());


        try {
            subject.login(token);
        }catch (AuthenticationException ex){

            return AdminResponseUtil.fail(AdminResponseCode.ADMIN_INVALID_AUTH);
        }

        //4.认证通过，修改ip / 登录时间

        String ip = request.getRemoteAddr();
        Date time = new Date();


        DtsAdmin dtsAdmin = (DtsAdmin) subject.getPrincipal();

        int rows = dtsAdminService.updateAdminById(dtsAdmin.getId(),ip,time);

        if (rows == 0){
            LOGGER.warn("[AdminAuthController:login]-->[认证成功以后，修改ip和登录时间失败！]" +
                                     "-->[未知]-->[未知]-->[id:ip:time]:{}:{}:{}",dtsAdmin.getId(),ip,time);
        }

        //5.封装数据
        //获取shiro存储subjectsession的标识
        Serializable id = subject.getSession(true).getId();

        System.out.println("id = " + id);

        return ResponseUtil.ok(id);
    }


    /**
     * 退出登录接口
     * @return
     */
    @PostMapping("logout")
    public Object logout(){

        Subject subject = SecurityUtils.getSubject();

        subject.logout();

        return ResponseUtil.ok();
    }


    /**
     * 获取用户信息
     * @return
     */
    @GetMapping("info")
    public Object info(){

        //1.获取当前登录的用户
        DtsAdmin dtsAdmin = AuthSupport.currentUser();
        //2.获取容器对象

        //3.处理返回结果 【调用业务处理返回结果】
        Map<String,Object> data =  dtsAdminService.findAdminInfo(dtsAdmin,applicationContext);

        //4.返回结果
        return ResponseUtil.ok(data);
    }


}
